package com.autumn.platform.web.bind;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.ConfigurablePropertyAccessor;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.method.annotation.InitBinderDataBinderFactory;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.InvocableHandlerMethod;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;

import com.autumn.platform.web.argumentresolver.BodyAndModelHandlerMethodArgumentResolver;
import com.autumn.platform.web.argumentresolver.MavContainerHandlerMethodArgumentResolver;
import com.autumn.platform.web.argumentresolver.MethodHandlerMethodArgumentResolver;
import com.autumn.platform.web.argumentresolver.RequestHandlerMethodArgumentResolver;
import com.autumn.platform.web.argumentresolver.SessionUserHandlerMethodArgumentResolver;

public class RelaxedRequestMappingHandlerAdapter extends RequestMappingHandlerAdapter {

    @Override
    protected InitBinderDataBinderFactory createDataBinderFactory(List<InvocableHandlerMethod> binderMethods) throws Exception {
        return new RelaxedServletRequestDataBinderFactory(binderMethods, getWebBindingInitializer());
    }

    @Override
    public void afterPropertiesSet() {
        setDefaultCustomArgumentResolvers();
        super.afterPropertiesSet();
    }

    private void setDefaultCustomArgumentResolvers() {
        // 获取所有的自定义参数解析器
        List<HandlerMethodArgumentResolver> resolvers = this.getCustomArgumentResolvers();
        if (null == resolvers) {
            resolvers = new ArrayList<HandlerMethodArgumentResolver>();
            this.setCustomArgumentResolvers(resolvers);
        }

        // 添加新的自定义参数解析器
        resolvers.addAll(0, this.getDefaultCustomArgumentResolvers());

        List<HttpMessageConverter<?>> converters = this.getMessageConverters();
        ConfigurablePropertyAccessor access = PropertyAccessorFactory.forDirectFieldAccess(this);
        @SuppressWarnings("unchecked")
        List<Object> requestResponseBodyAdvice = (List<Object>) access.getPropertyValue("requestResponseBodyAdvice");
        BodyAndModelHandlerMethodArgumentResolver resolver = new BodyAndModelHandlerMethodArgumentResolver(converters, requestResponseBodyAdvice);
        resolvers.add(resolver);
    }

    private List<HandlerMethodArgumentResolver> getDefaultCustomArgumentResolvers() {
        List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();
        resolvers.add(new MavContainerHandlerMethodArgumentResolver());
        resolvers.add(new MethodHandlerMethodArgumentResolver());
        resolvers.add(new RequestHandlerMethodArgumentResolver());
        resolvers.add(new SessionUserHandlerMethodArgumentResolver());
        return resolvers;
    }
}
